﻿/***************************************************************
 * 开发人员：网魂小兵@http://www.mozlite.com
 * 
 * 应用程序上下文。
 * 
 * 最后修改：2011-10-29
 * ************************************************************/
namespace Mozlite
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web;
    using System.Collections;
    using System.Collections.Specialized;
    using Mozlite.Common.Configuration;
    using Mozlite.Common;

    /// <summary>
    /// 应用程序上下文。
    /// </summary>
    public sealed class AppContext
    {
        #region initializer
        private AppContext()
        {
            this.Items = new HybridDictionary();
            this.RequestStart = DateTime.Now;
            this.pageIndex = -1;
            this.Initialize(new NameValueCollection(), null, null, null);
        }

        private AppContext(Uri uri, string siteUrl)
        {
            this.Items = new HybridDictionary();
            this.RequestStart = DateTime.Now;
            this.pageIndex = -1;
            this.Initialize(new NameValueCollection(), uri, uri.ToString(), siteUrl);
        }

        private AppContext(HttpContext context, bool includeQS = true)
        {
            this.Items = new HybridDictionary();
            this.RequestStart = DateTime.Now;
            this.pageIndex = -1;
            this.context = context;
            if (includeQS)
            {
                this.Initialize(new NameValueCollection(context.Request.QueryString), context.Request.Url, context.Request.RawUrl, this.GetSiteUrl());
            }
            else
            {
                this.Initialize(null, context.Request.Url, context.Request.RawUrl, this.GetSiteUrl());
            }
        }

        private string GetSiteUrl()
        {
            string url = this.context.Request.Url.Host;
            int port = this.context.Request.Url.Port;
            if (port != 80)
                url += ":" + port;
            return Globals.Combine(url, Globals.ApplicationUrl);
        }

        private void Initialize(NameValueCollection qs, Uri uri, string rawUrl, string siteUrl)
        {
            this.QueryString = qs;
            this.SiteUrl = siteUrl;
            this.Uri = uri;
            this.RawUrl = rawUrl;
        }

        private static void SaveContextToStore(AppContext context)
        {
            if (context.IsWebRequest)
            {
                context.Context.Items[dataStoreKey] = context;
            }
            else
            {
                appContext = context;
            }
        }

        private HttpContext context;
        /// <summary>
        /// 获取当前HTTP上下文。
        /// </summary>
        public HttpContext Context
        {
            get
            {
                if (context == null)
                    context = HttpContext.Current;
                return context;
            }
        }
        /// <summary>
        /// 获取是否为HTTP请求。
        /// </summary>
        public bool IsWebRequest
        {
            get { return this.Context != null; }
        }

        private static readonly string dataStoreKey = "Mozlite.AppContext";
        [ThreadStatic]
        private static AppContext appContext = null;

        /// <summary>
        /// 创建应用程序上下文。
        /// </summary>
        /// <param name="context">HTTP上下文对象实例。</param>
        /// <returns>返回应用程序上下文。</returns>
        public static AppContext Create(HttpContext context)
        {
            AppContext engine = new AppContext(context, true);
            SaveContextToStore(engine);
            return engine;
        }
        /// <summary>
        /// 创建应用程序上下文。
        /// </summary>
        /// <returns>返回应用程序上下文。</returns>
        public static AppContext Create()
        {
            AppContext context;
            SiteSettings siteSettings = SiteSettings.Current;
            try
            {
                context = new AppContext(new Uri(siteSettings.SiteUrl), siteSettings.SiteUrl);
            }
            catch {
                context = new AppContext();
            }
            SaveContextToStore(context);
            return context;
        }
        /// <summary>
        /// 获取应用程序上下文。
        /// </summary>
        public static AppContext Current
        {
            get
            {
                HttpContext current = HttpContext.Current;
                if (current != null)
                {
                    if (current.Items.Contains(dataStoreKey))
                    {
                        return (current.Items[dataStoreKey] as AppContext);
                    }
                    AppContext context = new AppContext(current, true);
                    SaveContextToStore(context);
                    return context;
                }
                if (appContext == null)
                {
                    SaveContextToStore(Create());
                }
                if (appContext == null)
                {
                    throw new Exception("No AppContext exists in the Current Application. AutoCreate fails since HttpContext.Current is not accessible.");
                }
                return appContext;
            }
        }

        /// <summary>
        /// 获取当前键的缓存对象实例。
        /// </summary>
        /// <param name="key">缓存键。</param>
        /// <returns>返回当前键的缓存对象实例。</returns>
        public object this[string key]
        {
            get
            {
                return this.Items[key];
            }
            set
            {
                this.Items[key] = value;
            }
        }
        /// <summary>
        /// 获取缓存集合。
        /// </summary>
        public IDictionary Items
        {
            get;
            private set;
        }
        /// <summary>
        /// 获取请求开始时间。
        /// </summary>
        public DateTime RequestStart { get; private set; }

        private int pageIndex = -1;
        /// <summary>
        /// 获取当前页码从1开始。
        /// </summary>
        public int PageIndex
        {
            get
            {
                if (this.pageIndex == -1)
                    this.pageIndex = this.QueryString["page"].ToInt32(1);
                if (this.pageIndex < 1)
                    this.pageIndex = 1;
                return this.pageIndex;
            }
        }
        /// <summary>
        /// 获取查询字符串集合。
        /// </summary>
        public NameValueCollection QueryString { get; private set; }
        /// <summary>
        /// 获取当前URL实例。
        /// </summary>
        public Uri Uri { get; private set; }
        /// <summary>
        /// 获取原URL地址字符串。
        /// </summary>
        public string RawUrl { get; private set; }
        /// <summary>
        /// 获取网站地址。
        /// </summary>
        public string SiteUrl
        {
            get;
            private set;
        }
        #endregion

        #region helper
        private SiteDomain siteDomain;
        /// <summary>
        /// 获取当前域名实例对象。
        /// </summary>
        public SiteDomain SiteDomain {
            get
            {
                if (siteDomain == null)
                {
                    if (SiteDomains.LoadSites().TryGetValue("." + this.Uri.DnsSafeHost, out siteDomain) && !siteDomain.Enabled)
                        siteDomain = null;
                } 
                return siteDomain;
            }
        }
        /// <summary>
        /// 获取载入所消耗的时间。
        /// </summary>
        /// <param name="format">输出格式。</param>
        /// <param name="unit">单位，提供两种，一种“MS”毫秒，一种“S”秒（如果不是“MS”则都为“S”）。</param>
        /// <returns>返回格式化后的字符串。</returns>
        public string GetLoadedCost(string format = "F5", string unit = "MS") {
            TimeSpan span = (TimeSpan)(DateTime.Now - RequestStart);
            if(unit == null || unit.ToUpper() != "MS")
                return span.TotalSeconds.ToString(format);
            return span.TotalMilliseconds.ToString(format);
        }

        private User user;
        /// <summary>
        /// 获取或设置当前用户实例。
        /// </summary>
        public User User
        {
            get
            {
                if (this.user == null)
                {
                    this.user = Users.GetUser(true);
                }
                return this.user;
            }
            set
            {
                this.user = value;
            }
        }
        private UserProfile profile;
        /// <summary>
        /// 获取或设置当前用户档案。
        /// </summary>
        public UserProfile Profile
        {
            get
            {
                if (this.profile == null)
                {
                    this.profile = Users.GetProfile(this.User.UserID) ;
                }
                return this.profile;
            }
            set
            {
                this.profile = value;
            }
        }

        /// <summary>
        /// 获取用户ID。
        /// </summary>
        public int UserID {
            get {
                return this.User.UserID;
            }
        }
        #endregion
    }
}
